/**
 * HTTP请求封装工具
 * 基于Nuxt 3的useFetch和$fetch，提供统一的请求处理、错误处理、拦截器等功能
 * 适用于LiveConsult项目的实际使用场景
 */

import { $fetch } from 'ofetch';
import type {
  RequestConfig,
  ApiResponse,
  ExtendedUseFetchOptions,
  ExtendedFetchOptions,
} from '~/api/types/http';
import { getEnvFromUrl } from '~/utils/env';

// 获取环境标识
const env = getEnvFromUrl();

// 构建API基础URL
const BASE_URL = env
  ? `https://appoint-${env}.pgxinli.com`
  : 'https://appoint.pgxinli.com';

// 全局orgId管理实例
let orgIdManager: ReturnType<typeof useOrgId> | null = null;

/**
 * 获取orgId管理器实例
 */
function getOrgIdManager() {
  if (!orgIdManager) {
    orgIdManager = useOrgId();
  }
  return orgIdManager;
}

/**
 * 获取当前orgId
 */
function getOrgId(): string {
  const manager = getOrgIdManager();
  return manager.getOrgId();
}

/**
 * HTTP错误类
 */
class HttpError extends Error {
  code: number;
  data?: any;

  constructor(message: string, code: number, data?: any) {
    super(message);
    this.name = 'HttpError';
    this.code = code;
    this.data = data;
  }
}

/**
 * HTTP请求客户端类
 */
class HttpClient {
  private baseURL: string;
  private defaultConfig: RequestConfig;

  constructor(baseURL: string) {
    this.baseURL = baseURL;
    this.defaultConfig = {
      timeout: 10000,
      showLoading: false,
      showError: true,
      requireAuth: true,
      retry: 1,
    };
  }

  /**
   * 请求拦截器
   */
  private async onRequest(options: any, config: RequestConfig) {
    // 显示加载状态
    if (config.showLoading) {
      this.showLoading(true);
    }

    // 设置基础headers
    options.headers = {
      'Content-Type': 'application/json',
      ...options.headers,
    };

    // 添加认证token
    if (config.requireAuth !== false) {
      const token = useCookie('auth-token');
      if (token.value) {
        options.headers['Authorization'] = `Bearer ${token.value}`;
      }
    }

    // 自动添加orgId参数
    const orgId = getOrgId();
    if (orgId) {
      // 对于 GET 请求，添加到 query 参数中
      if (options.method === 'GET' || !options.method) {
        if (options.query) {
          options.query.orgId = orgId;
        } else {
          options.query = { orgId };
        }
      }

      // 对于 POST/PUT/DELETE 请求，添加到 body 中
      if (
        options.body &&
        typeof options.body === 'object' &&
        !options.body.constructor.name.includes('FormData')
      ) {
        options.body.orgId = orgId;
      }

      // 同时也添加到 params 中作为备用（兼容其他情况）
      if (options.params) {
        options.params.orgId = orgId;
      } else {
        options.params = { orgId };
      }
    }

    return options;
  }

  /**
   * 响应拦截器
   */
  private async onResponse<T>(response: ApiResponse<T>, config: RequestConfig) {
    // 隐藏加载状态
    if (config.showLoading) {
      this.showLoading(false);
    }

    // 处理业务错误
    if (response.code !== 200 && response.code !== 0) {
      const error = new HttpError(
        response.message || '请求失败',
        response.code,
        response
      );

      if (config.showError) {
        this.showError(error.message);
      }

      if (config.customErrorHandler) {
        config.customErrorHandler(error);
      }

      throw error;
    }

    return response;
  }

  /**
   * 错误处理
   */
  private async onResponseError(error: any, config: RequestConfig) {
    // 隐藏加载状态
    if (config.showLoading) {
      this.showLoading(false);
    }

    let httpError: HttpError;

    if (error.response) {
      const { status, statusText, _data } = error.response;
      const message = _data?.message || statusText || '请求失败';
      httpError = new HttpError(message, status, _data);

      // 处理特定状态码
      switch (status) {
        case 401:
          await this.handleUnauthorized();
          break;
        case 403:
          if (config.showError) this.showError('没有权限访问该资源');
          break;
        case 404:
          if (config.showError) this.showError('请求的资源不存在');
          break;
        case 500:
          if (config.showError) this.showError('服务器内部错误，请稍后重试');
          break;
        default:
          if (config.showError) this.showError(message);
      }
    } else if (error.name === 'TimeoutError') {
      httpError = new HttpError('请求超时，请稍后重试', 408);
      if (config.showError) this.showError('请求超时，请稍后重试');
    } else {
      httpError = new HttpError('网络连接失败，请检查网络设置', 0);
      if (config.showError) this.showError('网络连接失败，请检查网络设置');
    }

    if (config.customErrorHandler) {
      config.customErrorHandler(httpError);
    }

    throw httpError;
  }

  /**
   * 处理未授权
   */
  private async handleUnauthorized() {
    const token = useCookie('auth-token');
    token.value = null;

    // 如果不在登录页，则跳转到登录页
    if (process.client) {
      const route = useRoute();
      if (route.path !== '/login') {
        await navigateTo('/login');
      }
    }
  }

  /**
   * 显示/隐藏加载状态
   */
  private showLoading(show: boolean) {
    if (process.client) {
      const loadingState = useState('http.loading', () => false);
      loadingState.value = show;
    }
  }

  /**
   * 显示错误提示
   */
  private showError(message: string) {
    // 可以集成到Toast组件或其他提示组件中
    console.error('HTTP Error:', message);

    // 示例：可以在这里集成全局通知组件
    // const { $toast } = useNuxtApp()
    // $toast.error(message)
  }

  /**
   * 创建通用的 useFetch 配置
   */
  private createFetchOptions<T>(
    method: string,
    config: RequestConfig,
    options: ExtendedUseFetchOptions<T>,
    body?: any
  ) {
    return {
      baseURL: this.baseURL,
      method: method as any,
      body,
      timeout: config.timeout,
      retry: config.retry,
      ...options,
      onRequest: ({ options: reqOptions }: { options: any }) =>
        this.onRequest(reqOptions, config),
      onResponse: ({ response }: { response: any }) =>
        this.onResponse(response._data, config),
      onResponseError: ({ error }: { error: any }) =>
        this.onResponseError(error, config),
    } as any;
  }

  /**
   * GET请求 - 使用useFetch（适用于SSR和数据缓存）
   */
  async get<T = any>(url: string, options: ExtendedUseFetchOptions<T> = {}) {
    const config = { ...this.defaultConfig, ...options };
    const fetchOptions = this.createFetchOptions('GET', config, options);

    return await useFetch<ApiResponse<T>>(url, fetchOptions);
  }

  /**
   * POST请求 - 使用useFetch
   */
  async post<T = any>(
    url: string,
    body?: any,
    options: ExtendedUseFetchOptions<T> = {}
  ) {
    const config = { ...this.defaultConfig, ...options };
    const fetchOptions = this.createFetchOptions('POST', config, options, body);

    return await useFetch<ApiResponse<T>>(url, fetchOptions);
  }

  /**
   * PUT请求 - 使用useFetch
   */
  async put<T = any>(
    url: string,
    body?: any,
    options: ExtendedUseFetchOptions<T> = {}
  ) {
    const config = { ...this.defaultConfig, ...options };
    const fetchOptions = this.createFetchOptions('PUT', config, options, body);

    return await useFetch<ApiResponse<T>>(url, fetchOptions);
  }

  /**
   * DELETE请求 - 使用useFetch
   */
  async delete<T = any>(url: string, options: ExtendedUseFetchOptions<T> = {}) {
    const config = { ...this.defaultConfig, ...options };
    const fetchOptions = this.createFetchOptions('DELETE', config, options);

    return await useFetch<ApiResponse<T>>(url, fetchOptions);
  }

  /**
   * 使用$fetch的请求方法（适用于客户端操作）
   */
  async request<T = any>(url: string, options: ExtendedFetchOptions = {}) {
    const config = { ...this.defaultConfig, ...options };
    const requestOptions = await this.onRequest(
      {
        baseURL: this.baseURL,
        timeout: config.timeout,
        retry: config.retry,
        ...options,
      },
      config
    );

    try {
      const response = await $fetch<ApiResponse<T>>(url, requestOptions);
      return await this.onResponse(response, config);
    } catch (error) {
      await this.onResponseError(error, config);
      throw error;
    }
  }

  /**
   * 获取认证头
   */
  private getAuthHeaders(config: RequestConfig): Record<string, string> {
    const headers: Record<string, string> = {};

    if (config.requireAuth !== false) {
      const token = useCookie('auth-token');
      if (token.value) {
        headers['Authorization'] = `Bearer ${token.value}`;
      }
    }

    return headers;
  }

  /**
   * 执行带加载状态的请求
   */
  private async executeWithLoading<T>(
    config: RequestConfig,
    requestFn: () => Promise<T>
  ): Promise<T> {
    try {
      if (config.showLoading) {
        this.showLoading(true);
      }

      const result = await requestFn();

      if (config.showLoading) {
        this.showLoading(false);
      }

      return result;
    } catch (error) {
      if (config.showLoading) {
        this.showLoading(false);
      }
      throw error;
    }
  }

  /**
   * 文件上传
   */
  async upload<T = any>(
    url: string,
    formData: FormData,
    options: RequestConfig = {}
  ) {
    const config = { ...this.defaultConfig, ...options };

    return await this.executeWithLoading(config, async () => {
      const headers = this.getAuthHeaders(config);

      const response = await $fetch<ApiResponse<T>>(url, {
        baseURL: this.baseURL,
        method: 'POST',
        body: formData,
        headers,
        timeout: config.timeout || 30000, // 文件上传超时时间更长
      });

      return await this.onResponse(response, config);
    });
  }

  /**
   * 文件下载
   */
  async download(url: string, filename?: string, options: RequestConfig = {}) {
    const config = { ...this.defaultConfig, ...options };

    return await this.executeWithLoading(config, async () => {
      const headers = this.getAuthHeaders(config);

      const response = await $fetch(url, {
        baseURL: this.baseURL,
        method: 'GET',
        headers,
        responseType: 'blob',
      });

      // 创建下载链接
      if (process.client) {
        const blob = new Blob([response]);
        const downloadUrl = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.download = filename || 'download';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(downloadUrl);
      }
    });
  }

  /**
   * 使用useAsyncData的异步数据获取（适用于SSR数据预取）
   */
  async asyncData<T = any>(
    key: string,
    url: string,
    options: RequestConfig = {}
  ) {
    const config = { ...this.defaultConfig, ...options };

    return await useAsyncData<ApiResponse<T>>(key, async () => {
      try {
        const response = await $fetch<ApiResponse<T>>(url, {
          baseURL: this.baseURL,
          timeout: config.timeout,
          retry: config.retry,
        });
        return await this.onResponse(response, config);
      } catch (error) {
        await this.onResponseError(error, config);
        throw error;
      }
    });
  }
}

// 创建HTTP客户端实例
export const http = new HttpClient(BASE_URL);

// 导出便捷方法
export const {
  get,
  post,
  put,
  delete: del,
  request,
  upload,
  download,
  asyncData,
} = http;

// 导出HTTP错误类
export { HttpError };
